/**
 * 文件名：@AbstractResponseBodyDecoder.java <br/>
 * 包名：cn.efunbox.afw.soa.client.netflix.feign.support <br/>
 * 项目名：afw-soa <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.soa.client.netflix.feign.support;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.Charset;

import feign.FeignException;
import feign.Response;
import feign.Response.Body;
import feign.codec.DecodeException;
import feign.codec.Decoder;

/**
 * 类名：AbstractResponseBodyDecoder  <br />
 *
 * 功能：数据体解码
 *
 * @author xtwin <br />
 * 创建时间：2016年7月24日 下午3:56:34  <br />
 * @version 2016年7月24日
 */
public abstract class AbstractResponseBodyDecoder implements Decoder {
	
	// 字符集
	protected Charset charset = Charset.forName("UTF-8");

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月24日 下午3:56:45<br/>
	 * 
	 * @param response
	 * @param type
	 * @return
	 * @throws IOException
	 * @throws DecodeException
	 * @throws FeignException <br/>
	 * @see feign.codec.Decoder#decode(feign.Response, java.lang.reflect.Type)
	 */
	@Override
	public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
		// 取出响应体
		Body body = response.body();
		
		if (null == body) {
			return null;
		}
		
		// 读取数据体
		byte[] data = readBody(response, type);
		
		if (null == data || data.length == 0) {
			return null;
		}
		
		return doDecode(response, type, data);
	}
	
	/**
	 * 功能：执行数据体编码 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月24日 下午4:03:17 <br/>
	 */
	protected abstract Object doDecode(Response response, Type type, byte[] data);

	/**
	 * 功能： 读取数据体 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月24日 下午4:01:31 <br/>
	 */
	protected byte[] readBody(Response response, Type type) throws IOException {
		try (InputStream is = response.body().asInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(1024)) {
			byte[] buf = new byte[1024];
			while (true) {
				int len = is.read(buf);
				if (len == -1) {
					break;
				}
				
				// 将内容写到缓冲区
				baos.write(buf, 0, len);
			}
			
			return baos.toByteArray();
		}
	}

	/**
	 * @version 2016年7月24日-下午4:05:30
	 */
	public void setCharset(Charset charset) {
		this.charset = charset;
	}
}